﻿/*
 * BitmapBlocks
 * 
 * initial implementation : 3.12.2008
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see Petra.Gis.License.txt
 */
using System;
using System.Windows;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Media.Imaging;


namespace Petra.Gis.ImagingServices.Tiff
{
  public class BitmapBlocks : IEnumerable<BitmapBlock>
  {

    protected BitmapBlock[] _blocks;
    //protected BitmapPage _parent;
    protected BlockBitmapSource _parent;
    protected BitmapSource _image;




    protected BitmapBlocks(int numItems)
    {
      _blocks = new BitmapBlock[numItems];
    }





    internal BitmapBlocks(BlockBitmapSource parent, BitmapSource image)
      : this(parent.TiffMetadata.NumBlocks)
    {
      _parent = parent;
      _image = image;
    }




    public BitmapBlock this[int index]
    {
      get 
      {
        if (_blocks[index] == null)
          _blocks[index] = createBitmapBlock(_parent.TiffMetadata, index);

        return _blocks[index];
      }
    }




    public IEnumerator<BitmapBlock> GetEnumerator()
    {
      return (IEnumerator<BitmapBlock>)_blocks.GetEnumerator();
    }


    IEnumerator IEnumerable.GetEnumerator()
    {
      return GetEnumerator();
    }






    public int Length 
    {
      get { return _blocks.Length; }
    }




    
    protected BitmapBlock createBitmapBlock(Metadata _metadata, int blockId)
    {

      if (blockId < 0 || blockId > _metadata.NumBlocks)
        throw new ArgumentOutOfRangeException("invalid index of block " + blockId.ToString());

      Int32Rect blockSize;

      int numBlVertical = _metadata.NumBlocksVertical;
      int numBlHorizontal = _metadata.NumBlocksHorizontal;
      int BlHeight = _metadata.BlockHeight;
      int BlWidth = _metadata.BlockWidth;
      int ImgHeight = _metadata.Height;
      int ImgWidth = _metadata.Width;

      int y = blockId / numBlHorizontal;
      //int x = blockId - (y * numBlHorizontal);
      int x = blockId % numBlHorizontal;

      blockSize = new Int32Rect();
      blockSize.X = x * BlWidth;
      blockSize.Y = y * BlHeight;
      blockSize.Width = ((blockSize.X + BlWidth) > ImgWidth) ? (ImgWidth - blockSize.X) : BlWidth;
      blockSize.Height = ((blockSize.Y + BlHeight) > ImgHeight) ? (ImgHeight - blockSize.Y) : BlHeight;

      if (_parent != null)
      {
        // file based tiff image
        if (_metadata.PlanarConfiguration == PlanarConfigurationType.Contignous)
          return new ContigousBitmapBlock(_parent, blockSize, blockId);
        else
          return new SeparatedBitmapBlock(_parent, blockSize, (blockId * _metadata.SamplesPerPixel));
      }
      else
      {
        // in memory tiff image (BitmapPage)
        // prepare block for this image
        if (_image != null)
        {
          throw new ApplicationException("sorry create separate block from image unsupported now");
          //existing image
          //if (_metadata.PlanarConfiguration == PlanarConfigurationType.Contignous)
          //  return new ContigousBitmapBlock(_parent, _image, blockSize, MemBitmapOpType.WorkOnExisting);
          //else
          //  return new SeparatedBitmapBlock(this, blockSize, _metadata, blockId * _metadata.SamplesPerPixel);
        }
        else
        {
          //empty image
          if (_metadata.PlanarConfiguration == PlanarConfigurationType.Contignous)
            return new ContigousBitmapBlock(_parent, blockSize, blockId);
          else
            return new SeparatedBitmapBlock(_parent, blockSize, blockId * _metadata.SamplesPerPixel);
        }

      }
    }
  }
}
